#pragma once

#include <rs_driver/api/lidar_driver.hpp>
#include <rs_driver/msg/pcl_point_cloud_msg.hpp>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>

#include <QDebug>
#include <QTimer>
#include <QWidget>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <Poco/Thread.h>

using namespace robosense::lidar;
using namespace pcl::visualization;

typedef PointCloudT<PointXYZI> PointCloudMsg;

class LidarDriverX : public QWidget 
{
    Q_OBJECT

public:
    LidarDriverX(QWidget *parent = nullptr, RSDriverParam param = RSDriverParam());
    ~LidarDriverX();

    void Start();
    void Stop();

private:
    void processCloud(void);
    void exceptionCallback(const Error &code);
    std::shared_ptr<PointCloudMsg> pointCloudGetCallback();
    void pointCloudPutCallback(std::shared_ptr<PointCloudMsg> msg);

    std::shared_ptr<PCLVisualizer> pcl_viewer;
    vtkSmartPointer<vtkRenderWindowInteractor> vtk_interactor;
    std::mutex mtx_viewer;

    QTimer* timer;

    SyncQueue<std::shared_ptr<PointCloudMsg>> free_cloud_queue;
    SyncQueue<std::shared_ptr<PointCloudMsg>> stuffed_cloud_queue;

    RSDriverParam rs_driver_param;

    bool to_exit_process = false;
    std::thread cloud_handle_thread;
    LidarDriver<PointCloudMsg> driver;
    Poco::Thread _threadCloudHandle;
    static void threadCloudHandle(void *pContext);
    void StartCloudHandle(void);

private slots:
    void updatePointCloud();
};